package com.gzhryc.shared_device.oem.h5.agent.mng.controllers.bxscn;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.data.dto.AjaxResult;
import com.gzhryc.common.data.dto.ListResult;
import com.gzhryc.common.excel.ExcelTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.kafka.JFKafkaProducer;
import com.gzhryc.common.kafka.KafkaProducerFactory;
import com.gzhryc.common.kafka.models.KafkaMessage;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.DateBranchHelper;
import com.gzhryc.servlet.DtoConstants;
import com.gzhryc.servlet.WebUtils;
import com.gzhryc.servlet.annotation.Route;
import com.gzhryc.shared_device.base.enums.EOperatorType;
import com.gzhryc.shared_device.base.enums.EPayType;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.base.models.OrderLogContent;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNOrder;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNOrderLog;
import com.gzhryc.shared_device.bxscn.code.dao.enums.BXSCNOrderEnum;
import com.gzhryc.shared_device.bxscn.code.dao.enums.EBXSCNCostMode;
import com.gzhryc.shared_device.bxscn.code.services.BXSCNOrderLogService;
import com.gzhryc.shared_device.bxscn.code.services.BXSCNOrderService;
import com.gzhryc.shared_device.bxscn.code.services.dto.BXSCNOrderSearch;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayOrder;
import com.gzhryc.shared_device.common.payment.dao.db.WXRefundOrder;
import com.gzhryc.shared_device.common.payment.services.WXPayOrderService;
import com.gzhryc.shared_device.common.payment.services.WXRefundOrderService;
import com.gzhryc.shared_device.oem.code.KafkaEventConstants;
import com.gzhryc.shared_device.oem.code.PayServiceFactory;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.member.services.MemberBusinessOrderService;
import com.gzhryc.shared_device.oem.code.order.RedisCacheManager;
import com.gzhryc.shared_device.oem.code.order.event.OrderFinishEvent;
import com.gzhryc.shared_device.oem.code.profit.dao.db.BusinessOrder;
import com.gzhryc.shared_device.oem.code.profit.dao.enums.BusinessOrderEnum;
import com.gzhryc.shared_device.oem.code.profit.service.BusinessOrderService;
import com.gzhryc.shared_device.oem.code.user.dao.db.User;
import com.gzhryc.shared_device.oem.h5.agent.mng.WebConstants;

/**
 * 无人值守设备租借归还订单
 * @version 2023-11-12
 */
public class BXSCNOrderController {

    static Logger log = Logger.getLogger(BXSCNOrderController.class);

    @Route("/bxscn/order/list.html")
    public String list(HttpServletRequest request) {
        request.setAttribute("payStateList", BXSCNOrderEnum.PayState.values());
        request.setAttribute("stateList", BXSCNOrderEnum.State.values());
        request.setAttribute("costModeList", EBXSCNCostMode.values());
        request.setAttribute("dateBranchItemList", DateBranchHelper.self().getYearDateBranchItems());
        return "/bxscn/order/list.html";
    }

    @Route(value = "/bxscn/order/list.data")
    public ListResult<BXSCNOrder> listData(HttpServletRequest request,HttpSession session) {
        ListResult<BXSCNOrder> result = new ListResult<>(DtoConstants.NULL_DATA, "暂无数据");
        BXSCNOrderSearch search = WebUtils.getParameter(request, BXSCNOrderSearch.class);
        String searchDate = WebUtils.getString(request,"searchDate");
        Integer pageNo = WebUtils.getInteger(request, "page", 1);
        Integer pageLimit = WebUtils.getInteger(request, "limit", WebConstants.PAGE_LIMIT);
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (loginUser != null) {
            search.setLeaseAgentId(loginUser.getId());
            try {
                if (StringTools.isNotBlank(searchDate)) {
                    String[] strings = searchDate.split(" - ");
                    if (strings.length == 2) {
                        Date startDate = DateUtils.parseDate(strings[0], "yyyy-MM-dd");
                        Date endDate = DateUtils.parseDate(strings[1], "yyyy-MM-dd");
                        search.setStartDate(startDate);
                        search.setEndDate(endDate);
                    }
                }
                Date dateBranch = new Date();
                if (StringTools.isNotBlank(search.getDateBranchId())) {
                    dateBranch = DateBranchHelper.getDateByItemId(search.getDateBranchId());
                }

                session.setAttribute("BXSCNOrderSearch", search);

                result.getBody().setTotal(BXSCNOrderService.self(dateBranch).countBySearch(search));
                List<BXSCNOrder> data = BXSCNOrderService.self(dateBranch).findBySearch(search, pageNo, pageLimit);
                if (data != null && data.size() > 0) {
                    result.setCode(DtoConstants.SUCCESS, null);
                    result.getBody().setData(data);
                }
            } catch (Exception e) {
                result.setMsg(e.getMessage());
            }
        }
        return result;
    }

    @Route("/bxscn/order/info.html")
    public String info(HttpServletRequest request) {
        String tradeNo = WebUtils.getString(request, "tradeNo");
        Date createDate = WebUtils.getDate(request, "createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (loginUser != null) {
            if (createDate == null) {
                createDate = new Date();
            }
            BXSCNOrder deviceOrder = BXSCNOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getLeaseAgentId() != null && deviceOrder.getLeaseAgentId().equals(loginUser.getId())) {
                WebUtils.setAttribute(request, deviceOrder);

                if (EPayType.WXPay.index().equals(deviceOrder.getPayType())) {
                    WXPayOrder payOrder = WXPayOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getPayTradeNo());
                    if (payOrder != null) {
                        request.setAttribute("payOrder", payOrder);
                        List<WXRefundOrder> refundOrderList = WXRefundOrderService.self(deviceOrder.getCreateDate()).findByBusinessTradeNo(payOrder.getBusinessTradeNo());
                        request.setAttribute("refundOrderList", refundOrderList);
                    }
                }
            }
        }
        request.setAttribute("businessType", EBusinessType.BXSCN);
        return "/bxscn/order/info.html";
    }

    @Route(value = "/bxscn/order/operate/record/list.data")
    public ListResult<OrderLogContent.LogItem> logListData(HttpServletRequest request) {
        ListResult<OrderLogContent.LogItem> result = new ListResult<>(DtoConstants.NULL_DATA, "暂无数据");
        String tradeNo = WebUtils.getString(request,"tradeNo");
        Date createDate = WebUtils.getDate(request,"createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (loginUser != null) {
            if (createDate == null) {
                createDate = new Date();
            }
            BXSCNOrder deviceOrder = BXSCNOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getLeaseAgentId() != null && deviceOrder.getLeaseAgentId().equals(loginUser.getId())) {
                BXSCNOrderLog orderLog = BXSCNOrderLogService.self(createDate).getByTradeNo(tradeNo);
                if (orderLog != null && StringTools.isNotBlank(orderLog.getContent())) {
                    OrderLogContent logContent = JsonTools.fromJson(orderLog.getContent(), OrderLogContent.class);
                    if (logContent != null) {
                        result.setCode(DtoConstants.SUCCESS, null);
                        result.getBody().setData(logContent.getItems());
                    }
                }
            }
        }
        return result;
    }

    @Route("/bxscn/order/operate/refund.html")
    public String refund(HttpServletRequest request) {
        String tradeNo = WebUtils.getString(request,"tradeNo");
        Date createDate = WebUtils.getDate(request,"createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (loginUser != null) {
            if (createDate == null) {
                createDate = new Date();
            }
            BXSCNOrder deviceOrder = BXSCNOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getLeaseAgentId() != null && deviceOrder.getLeaseAgentId().equals(loginUser.getId())) {
                request.setAttribute("refundMoneyStr", deviceOrder.getPayMoneyStr());
            }
        }
        return "/bxscn/order/refund.html";
    }

    @Route(value = {"/bxscn/order/operate/refund.do"})
    public AjaxResult doRefund(HttpServletRequest request, HttpSession session) {
        AjaxResult result = new AjaxResult(DtoConstants.EXECUTE_ERROR, "撤销订单失败");
        String tradeNo = WebUtils.getString(request, "tradeNo");
        Date createDate = WebUtils.getDate(request,"createDate");
        Double refundMoneyStr = WebUtils.getDouble(request,"refundMoneyStr");
        String refundNote = WebUtils.getString(request,"refundNote");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (StringTools.isNotBlank(tradeNo) && loginUser != null) {
            if (refundMoneyStr == null) {
                result.setMsg("请填写退款金额");
                return result;
            }
            if (StringTools.isBlank(refundNote)) {
                result.setMsg("请填写退款原因");
                return result;
            }
            if(createDate == null){
                createDate = new Date();
            }

            //检查分成
            BusinessOrder businessOrder = BusinessOrderService.self(createDate).getByTradeNo(tradeNo);
            if(businessOrder != null && (BusinessOrderEnum.DivideState.Finish.index().equals(businessOrder.getDivideState())
                    || BusinessOrderEnum.DivideState.CancelExecuting.index().equals(businessOrder.getDivideState()))){
                result.setMsg("订单已分成，请回滚分成后操作");
                return result;
            }

            try {
                BXSCNOrder deviceOrder = BXSCNOrderService.self(createDate).getByTradeNo(tradeNo);
                if(deviceOrder == null){
                    result.setMsg("未找到租借订单");
                    return result;
                }

                if(deviceOrder.getLeaseAgentId() != null && deviceOrder.getLeaseAgentId().equals(loginUser.getId())) {
                	OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE, WebConstants.PROGRAM_TYPE_NAME);
                    operateInfo.setOperator(EOperatorType.Agent.index(), loginUser.getFullName());
                    operateInfo.setOperateNote(refundNote);

                    Integer refundMoney = NumberTools.changeMoney(refundMoneyStr);
                    int refundResult = BXSCNOrderService.self(deviceOrder.getCreateDate()).refund(deviceOrder, refundMoney, PayServiceFactory.self(), operateInfo);
                    if (refundResult > 0) {
                        result.setCode(DtoConstants.SUCCESS, null);
                    }
                }else{
                    result.setMsg("无权限操作");
                }
            } catch (LogicException e) {
                result.setMsg(e.getMessage());
            }
        }
        return result;
    }

    @Route(value = { "/bxscn/order/operate/cancel.html" })
    public String cancel(HttpServletRequest request) {
        return "/bxscn/order/cancel.html";
    }

    @Route(value = { "/bxscn/order/operate/cancel.do" })
    public AjaxResult doCancel(HttpServletRequest request) {
        AjaxResult result = new AjaxResult(DtoConstants.EXECUTE_ERROR, "撤销失败");
        String tradeNo = WebUtils.getString(request, "tradeNo");
        Date createDate = WebUtils.getDate(request,"createDate");
        String note = WebUtils.getString(request, "note");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (StringTools.isNotBlank(tradeNo) && loginUser != null) {
            if (StringTools.isBlank(note)) {
                result.setMsg("请填撤销的原因");
                return result;
            }
            if(createDate == null){
                createDate = new Date();
            }

            //检查分成
            BusinessOrder businessOrder = BusinessOrderService.self(createDate).getByTradeNo(tradeNo);
            if(businessOrder != null && (BusinessOrderEnum.DivideState.Finish.index().equals(businessOrder.getDivideState())
                    || BusinessOrderEnum.DivideState.CancelExecuting.index().equals(businessOrder.getDivideState()))){
                result.setMsg("订单已分成，请回滚分成后操作");
                return result;
            }

            BXSCNOrder deviceOrder = BXSCNOrderService.self(createDate).getByTradeNo(tradeNo);
            if(deviceOrder != null && deviceOrder.getLeaseAgentId() != null && deviceOrder.getLeaseAgentId().equals(loginUser.getId())) {
            	OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE, WebConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator(EOperatorType.Agent.index(), loginUser.getFullName());
                operateInfo.setOperateNote(note);

                Date cancelDate = new Date();
                try {
                    int cancelResult = BXSCNOrderService.self(deviceOrder.getCreateDate()).cancel(deviceOrder, PayServiceFactory.self(), operateInfo);
                    if (cancelResult > 0) {
                        //清理缓存，避免定时器重复处理
                        RedisCacheManager.removeWorkingBXSCNDeviceOrder(deviceOrder.getTradeNo());
                        if (cancelResult == 2) {
                            deviceOrder = BXSCNOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getTradeNo());
                            //同步会员订单
                            MemberBusinessOrderService.self(deviceOrder.getCreateDate()).cancel(deviceOrder.getTradeNo(), deviceOrder.getMoney()
                                    , deviceOrder.getPayMoney(), deviceOrder.getWalletMoney());
                            BusinessOrderService.self(deviceOrder.getCreateDate()).cancel(deviceOrder.getTradeNo(), cancelDate);
                        }
                        result.setCode(DtoConstants.SUCCESS, null);
                    }
                } catch (LogicException e) {
                    result.setMsg(e.getMessage());
                }
            }else{
                result.setMsg("无权限操作");
            }
        }
        return result;
    }

    @Route("/bxscn/order/operate/finish.html")
    public String finish(HttpServletRequest request) {
        String tradeNo = WebUtils.getString(request,"tradeNo");
        Date createDate = WebUtils.getDate(request,"createDate");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (StringTools.isNotBlank(tradeNo) && loginUser != null) {
            if (createDate == null) {
                createDate = new Date();
            }
            BXSCNOrder deviceOrder = BXSCNOrderService.self(createDate).getByTradeNo(tradeNo);
            if (deviceOrder != null && deviceOrder.getLeaseAgentId() != null && deviceOrder.getLeaseAgentId().equals(loginUser.getId())) {
                request.setAttribute("payMoneyStr", deviceOrder.getPayMoneyStr());
            }
        }
        return "/bxscn/order/finish.html";
    }

    @Route(value = { "/bxscn/order/operate/finish.do" })
    public AjaxResult doFinish(HttpServletRequest request) {
        AjaxResult result = new AjaxResult(DtoConstants.EXECUTE_ERROR, "完成失败");
        String tradeNo = WebUtils.getString(request, "tradeNo");
        Date createDate = WebUtils.getDate(request,"createDate");
        Double payMoneyPrice = WebUtils.getDouble(request,"payMoneyStr");
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (StringTools.isNotBlank(tradeNo) && loginUser != null) {
            if (payMoneyPrice == null) {
                result.setMsg("请填写支付金额");
                return result;
            }

            if(createDate == null){
                createDate = new Date();
            }

            BXSCNOrder deviceOrder = BXSCNOrderService.self(createDate).getByTradeNo(tradeNo);
            if(deviceOrder == null){
                result.setMsg("未找到租借订单");
                return result;
            }
            if(deviceOrder.getLeaseAgentId() != null && deviceOrder.getLeaseAgentId().equals(loginUser.getId())) {
            	OperateInfo operateInfo = new OperateInfo(WebConstants.PROGRAM_TYPE, WebConstants.PROGRAM_TYPE_NAME);
                operateInfo.setOperator(EOperatorType.Agent.index(), loginUser.getFullName());
                operateInfo.setOperateNote("后台客服操作完成订单");

                try {
                    int finishResult = BXSCNOrderService.self(deviceOrder.getCreateDate()).finish(deviceOrder, NumberTools.changeMoney(payMoneyPrice), PayServiceFactory.self(), operateInfo);
                    if (finishResult > 0) {
                        //清理缓存，避免定时器重复处理
                        RedisCacheManager.removeWorkingBXSCNDeviceOrder(deviceOrder.getTradeNo());
                        if (finishResult == 2) {
                            deviceOrder = BXSCNOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getTradeNo());
                            //同步会员订单
                            MemberBusinessOrderService.self(deviceOrder.getCreateDate()).finish(deviceOrder.getTradeNo(), deviceOrder.getMoney(), deviceOrder.getPayMoney(),
                                    deviceOrder.getWalletMoney(),operateInfo);

                            //触发订单完成
                            JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
                            if (producer != null) {
                                OperateInfo temp = ClassTools.copy(new OperateInfo(), operateInfo);
                                OrderFinishEvent event = new OrderFinishEvent(EBusinessType.BXSCN.index(), deviceOrder.getTradeNo(), deviceOrder.getCreateDate(), temp);
                                KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_OrderFinish, JsonTools.toJson(event));
                                producer.send(kafkaMessage);
                            } else {
                                log.error("未初始化消息队列，订单{{0}}未触发完成事件", deviceOrder.getTradeNo());
                            }
                        }
                        result.setCode(DtoConstants.SUCCESS, null);
                    }

                } catch (LogicException e) {
                    result.setMsg(e.getMessage());
                }
            }else{
                result.setMsg("无权限操作");
            }
        }
        return result;
    }

    @Route(value = "/bxscn/order/excel/export.do")
    public void doExportExcel(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException {
        User loginUser = WebUtils.getAttribute(request, WebConstants.LOGIN_USER, User.class);
        if (loginUser != null) {
            String[] titles = {"设备序列号", "电池类型", "电池序列号", "租借网点ID", "租借网点名称", "租借网点地区", "租借机柜编号", "租借卡槽号"
                    , "归还网点ID", "归还网点名称", "归还网点地区", "归还机柜编号", "归还卡槽号", "会员ID", "会员名称", "会员手机号", "收费方式", "租借起始时间", "租借结束时间"
                    , "租借时长", "订单金额", "支付类型", "支付状态", "支付时间", "订单状态", "订单完成时间", "订单创建时间"};
            List<Object[]> data = new ArrayList<>();
            BXSCNOrderSearch search = WebUtils.getAttribute(session, "BXSCNOrderSearch", BXSCNOrderSearch.class);
            if (search == null) {
                search = new BXSCNOrderSearch();
            }
            Integer pageNo = 1;
            Integer pageLimit = WebConstants.PAGE_LIMIT;
            try {
                search.setLeaseAgentId(loginUser.getId());
                Date dateBranch = new Date();
                if (StringTools.isNotBlank(search.getDateBranchId())) {
                    dateBranch = DateBranchHelper.getDateByItemId(search.getDateBranchId());
                }
                List<BXSCNOrder> shopOrderList = BXSCNOrderService.self(dateBranch).findBySearch(search, pageNo, pageLimit);
                while (shopOrderList != null && shopOrderList.size() > 0) {
                    for (BXSCNOrder shopOrder : shopOrderList) {
                        Object[] objects = new Object[titles.length];
                        objects[0] = shopOrder.getTradeNo();
                        objects[1] = shopOrder.getBatteryTypeName();
                        objects[2] = shopOrder.getPortableBatterySn();
                        objects[3] = shopOrder.getLeasePlaceId();
                        objects[4] = shopOrder.getLeasePlaceName();
                        objects[5] = shopOrder.getPlaceAreaName();
                        objects[6] = shopOrder.getLeaseDeviceSn();
                        objects[7] = shopOrder.getLeaseSlotNum();
                        objects[8] = shopOrder.getRevertPlaceId();
                        objects[9] = shopOrder.getRevertPlaceName();
                        objects[10] = shopOrder.getRevertAreaName();
                        objects[11] = shopOrder.getRevertDeviceSn();
                        objects[12] = shopOrder.getRevertSlotNum();
                        objects[13] = shopOrder.getMemberId();
                        objects[14] = shopOrder.getMemberName();
                        objects[15] = shopOrder.getMemberPhone();
                        objects[16] = shopOrder.getCostModeName();
                        if (shopOrder.getStartDate() != null) {
                            objects[17] = DateFormatUtils.format(shopOrder.getStartDate(), "yyyy-MM-dd HH:mm:ss");
                        } else {
                            objects[17] = "";
                        }
                        if (shopOrder.getEndDate() != null) {
                            objects[18] = DateFormatUtils.format(shopOrder.getEndDate(), "yyyy-MM-dd HH:mm:ss");
                        } else {
                            objects[18] = "";
                        }
                        objects[19] = shopOrder.getUseDuration();
                        objects[20] = shopOrder.getMoneyStr();
                        objects[21] = shopOrder.getPayTypeName();
                        objects[22] = shopOrder.getPayStateName();
                        if (shopOrder.getPayDate() != null) {
                            objects[23] = DateFormatUtils.format(shopOrder.getPayDate(), "yyyy-MM-dd HH:mm:ss");
                        } else {
                            objects[23] = "";
                        }
                        objects[24] = shopOrder.getStateName();
                        if (shopOrder.getFinishDate() != null) {
                            objects[25] = DateFormatUtils.format(shopOrder.getFinishDate(), "yyyy-MM-dd HH:mm:ss");
                        } else {
                            objects[25] = "";
                        }
                        if (shopOrder.getCreateDate() != null) {
                            objects[26] = DateFormatUtils.format(shopOrder.getCreateDate(), "yyyy-MM-dd HH:mm:ss");
                        } else {
                            objects[26] = "";
                        }
                        data.add(objects);
                    }
                    pageNo = pageNo + 1;
                    shopOrderList = BXSCNOrderService.self(dateBranch).findBySearch(search, pageNo, pageLimit);
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }

            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
            String name = format.format(new Date());
            WebUtils.exportExcel(response, name);
            ExcelTools.export(response.getOutputStream(), "户外电池租借订单信息", null, titles, data);
        }
    }
}
